﻿using System;
using System.IO;

namespace LiveNet.Photos
{
    public sealed class Album
    {
        private readonly LivePhotos m_Photos;
        private readonly string m_Name;
        private readonly string m_Id;
        private readonly DateTime m_CreatedOn;
        private readonly DateTime m_LastModified;
        private readonly Uri m_AlbumUrl;
        private bool m_Deleted;

        internal Album(LivePhotos photosApi, string name, string id, DateTime createdOn, DateTime lastModified, Uri albumUrl)
        {
            m_Photos = photosApi;
            m_Name = name;
            m_AlbumUrl = albumUrl;
            m_LastModified = lastModified;
            m_CreatedOn = createdOn;
            m_Id = id; 
        }

        #region Properties
        /// <summary>
        /// Gets the name.
        /// </summary>
        /// <value>The name.</value>
        public string Name
        {
            get { return m_Name; }
        }

        /// <summary>
        /// Gets the id.
        /// </summary>
        /// <value>The id.</value>
        public string Id
        {
            get { return m_Id; }
        }

        /// <summary>
        /// Gets the created on.
        /// </summary>
        /// <value>The date the album was created on.</value>
        public DateTime CreatedOn
        {
            get { return m_CreatedOn; }
        }

        /// <summary>
        /// Gets the last modified.
        /// </summary>
        /// <value>The date the album was last modified.</value>
        public DateTime LastModified
        {
            get { return m_LastModified; }
        }

        /// <summary>
        /// Gets the album URL.
        /// </summary>
        /// <value>The album URL.</value>
        public Uri AlbumUrl
        {
            get { return m_AlbumUrl; }
        }

        /// <summary>
        /// Gets a value indicating whether this instance has been deleted.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance has been deleted; otherwise, <c>false</c>.
        /// </value>
        public bool HasBeenDeleted
        {
            get { return m_Deleted; }
        }
        #endregion

        #region Public Methods

        #region AddPhoto Methods
        /// <summary>
        /// Adds the photo.
        /// </summary>
        /// <param name="file">The filestream to be added.</param>
        /// <param name="filename">The filename (eg, Coventry.jpg).</param>
        /// <returns>The newly created Photo</returns>
        /// <exception cref="InvalidOperationException"></exception>
        /// <example>
        /// <code>
        /// // Create the instance of LivePhotos
        /// LivePhotos m_spaces = new LivePhotos("example@hotmail.com", DAT, AuthenticationToken.DomainAuthenticationToken);
        /// 
        /// // Get the album
        /// Album myAlbum = m_spaces.GetAlbum("myAlbum");
        /// 
        /// // Add the new photo
        /// Stream stream = fileUpload.PostedFile.InputStream;
        /// string filename = fileUpload.FileName;
        /// Photo winter = myAlbum.AddPhoto(stream, filename);
        /// </code>
        /// </example>
        public Photo AddPhoto(Stream file, string filename)
        {
            return AddPhoto(file, filename, string.Empty);
        }

        /// <summary>
        /// Adds the photo.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <param name="filename">The filename (eg, Coventry.jpg).</param>
        /// <param name="caption">The caption.</param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        /// <example>
        /// <code>
        /// // Create the instance of LivePhotos
        /// LivePhotos m_spaces = new LivePhotos("example@hotmail.com", DAT, AuthenticationToken.DomainAuthenticationToken);
        /// 
        /// // Get the album
        /// Album myAlbum = m_spaces.GetAlbum("myAlbum");
        /// 
        /// // Add the new photo
        /// Stream stream = fileUpload.PostedFile.InputStream;
        /// string filename = fileUpload.FileName;
        /// string caption = "This is a comment about winter";
        /// Photo winter = myAlbum.AddPhoto(stream, filename, caption);
        /// </code>
        /// </example>
        public Photo AddPhoto(Stream file, string filename, string caption)
        {
            if (HasBeenDeleted)
            {
                throw new InvalidOperationException(string.Format(LiveNetResources.AlbumDeletedAddException, "photo"));
            }

            if (string.IsNullOrEmpty(filename))
            {
                throw new ArgumentNullException("filename");
            }

            if (file != null)
            {
                // If the caption isn't set then there is no need to call the AddPhoto method with it as a parameter.
                if (string.IsNullOrEmpty(caption))
                {
                    return m_Photos.AddPhoto(file, AlbumUrl, filename);
                }
                else
                {
                    return m_Photos.AddPhoto(file, AlbumUrl, filename, caption);
                }
            }
            else
            {
                throw new ArgumentNullException("file");
            }
        }

        /// <summary>
        /// Adds the photo.
        /// </summary>
        /// <param name="file">The file (include full path).</param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        /// <example>
        /// <code>
        /// // Create the instance of LivePhotos
        /// LivePhotos m_spaces = new LivePhotos("example@hotmail.com", DAT, AuthenticationToken.DomainAuthenticationToken);
        /// 
        /// // Get the album
        /// Album myAlbum = m_spaces.GetAlbum("myAlbum");
        /// 
        /// // Add the new photo
        /// string file = openFileDialog1.FileName;
        /// Photo winter = myAlbum.AddPhoto(file);
        /// </code>
        /// </example>
        public Photo AddPhoto(string file)
        {
            return AddPhoto(file, string.Empty);
        }

        /// <summary>
        /// Adds the photo.
        /// </summary>
        /// <param name="file">The file (include full path).</param>
        /// <param name="caption">The caption.</param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        /// <example>
        /// <code>
        /// // Create the instance of LivePhotos
        /// LivePhotos m_spaces = new LivePhotos("example@hotmail.com", DAT, AuthenticationToken.DomainAuthenticationToken);
        /// 
        /// // Get the album
        /// Album myAlbum = m_spaces.GetAlbum("myAlbum");
        /// 
        /// // Add the new photo
        /// string file = openFileDialog1.FileName;
        /// string caption = "This is a caption about winter";
        /// Photo winter = myAlbum.AddPhoto(file, caption);
        /// </code>
        /// </example>
        public Photo AddPhoto(string file, string caption)
        {
            if (HasBeenDeleted)
            {
                throw new InvalidOperationException(string.Format(LiveNetResources.AlbumDeletedAddException, "photo"));
            }

            if (File.Exists(file))
            {
                string filename = Path.GetFileName(file);

                using (Stream s = File.Open(file, FileMode.Open))
                {
                    // If the caption isn't set then there is no need to call the AddPhoto method with it as a parameter.
                    if (string.IsNullOrEmpty(caption))
                    {
                        return m_Photos.AddPhoto(s, AlbumUrl, filename);
                    }
                    else
                    {
                        return m_Photos.AddPhoto(s, AlbumUrl, filename, caption);
                    }
                }
            }
            else
            {
                throw new FileNotFoundException(LiveNetResources.ImageNotFoundException, file);
            }
        }
        #endregion

        /// <summary>
        /// Lists the photos.
        /// </summary>
        /// <returns>An array of photos that are in the given album</returns>
        /// <exception cref="InvalidOperationException"></exception>
        /// <example>
        /// <code>
        /// // Create the instance of LivePhotos
        /// LivePhotos m_spaces = new LivePhotos("example@hotmail.com", DAT, AuthenticationToken.DomainAuthenticationToken);
        /// 
        /// // Get the album
        /// Album myAlbum = m_spaces.GetAlbum("myAlbum");
        /// 
        /// // Get the photos in that album
        /// Photo[] myPhotos = myAlbum.ListPhotos();
        /// 
        /// foreach(Photo photo in myPhotos)
        /// {
        ///     Console.WriteLine(photo.Name);
        /// }
        /// </code>
        /// </example>
        public Photo[] ListPhotos()
        {
            if (HasBeenDeleted)
            {
                throw new InvalidOperationException(string.Format(LiveNetResources.AlbumDeletedListException, "photos"));
            }

            return m_Photos.ListPhotos(AlbumUrl);
        }

        /// <summary>
        /// Deletes this instance.
        /// </summary>
        /// <example>
        /// <code>
        /// // Create the instance of LivePhotos
        /// LivePhotos m_spaces = new LivePhotos("example@hotmail.com", DAT, AuthenticationToken.DomainAuthenticationToken);
        /// 
        /// // Get the album
        /// Album myAlbum = m_spaces.GetAlbum("myAlbum");
        /// 
        /// // Delete the album
        /// myAlbum.Delete();
        /// </code>
        /// </example>
        public void Delete()
        {
            if (!HasBeenDeleted && m_Photos.DeleteAlbum(this))
            {
                m_Deleted = true;
            }
        }
        #endregion
    }
}
